#ifndef __I2C_H
#define __I2C_H

#include <stdbool.h>
#include <stdint.h>

#define I2C_INFO(NAME, SCL, SDA, DELAY_US)                                     \
    static void NAME##_i2c_start() {                                           \
        SCL##_set_high();                                                      \
        SDA##_set_high();                                                      \
        delay_us(DELAY_US);                                                    \
        SDA##_set_low();                                                       \
        delay_us(DELAY_US);                                                    \
        SCL##_set_low();                                                       \
        delay_us(DELAY_US);                                                    \
    }                                                                          \
    static void NAME##_i2c_stop() {                                            \
        SDA##_set_low();                                                       \
        SCL##_set_high();                                                      \
        delay_us(DELAY_US);                                                    \
        SDA##_set_high();                                                      \
        delay_us(DELAY_US);                                                    \
    }                                                                          \
    static void NAME##_write_byte(uint8_t value) {                             \
        for (uint8_t i = 0; i < 8; i++) {                                      \
            if (value & 0x80)                                                  \
                SDA##_set_high();                                              \
            else                                                               \
                SDA##_set_low();                                               \
            value <<= 1;                                                       \
            delay_us(DELAY_US);                                                \
            SCL##_set_high();                                                  \
            delay_us(DELAY_US);                                                \
            SCL##_set_low();                                                   \
            delay_us(DELAY_US);                                                \
        }                                                                      \
    }                                                                          \
    static void NAME##_wait_ack() {                                            \
        SDA##_init(MODE_IN_FLOAT);                                             \
        SCL##_set_high();                                                      \
        delay_us(DELAY_US);                                                    \
        SCL##_set_low();                                                       \
        SDA##_init(MODE_PP);                                                   \
        delay_us(DELAY_US);                                                    \
    }                                                                          \
    static void NAME##_write(uint16_t value) {                                 \
        NAME##_i2c_start();                                                    \
        NAME##_write_byte(value >> 8);                                         \
        NAME##_wait_ack();                                                     \
        NAME##_write_byte(value);                                              \
        NAME##_wait_ack();                                                     \
        NAME##_i2c_stop();                                                     \
    }

#endif
